﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using SimplePersonManager.Contracts;

namespace SimplePersonManager.Tests
{
    [TestClass]
    public class SimplePersonManagerTests
    {
        SimplePersonManager _simplePersonManager;
        Mock<IRepository> _mockRepository;
        
        [TestInitialize]
        public void Setup()
        {
            _mockRepository = new Mock<IRepository>();
            _simplePersonManager = new SimplePersonManager(_mockRepository.Object);
        }

        [TestMethod]
        public void GetPeople_CallsRepositoryRetrieveAll()
        {
            var people = _simplePersonManager.GetPeople();

            _mockRepository.Verify(r => r.RetrieveAll(), Times.Once());
        }

        [TestMethod]
        public void GetPersonByName_WhenNameValid_CallsRepositoryRetrievePerson()
        {
            var personName = "personName";

            var person = _simplePersonManager.GetPersonByName(personName);

            _mockRepository.Verify(r => r.RetrievePerson(personName), Times.Once());
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void GetPersonByName_WhenNameEmpty_ThrowsArgumentException()
        {
            var personName = "";

            var person = _simplePersonManager.GetPersonByName(personName);
        }

        [TestMethod]
        public void SavePerson_WhenPersonValid_CallsRepositoryStorePerson()
        {
            var person = new Person();
            person.Name = "person name";

            _simplePersonManager.SavePerson(person);

            _mockRepository.Verify(r => r.StorePerson(person), Times.Once());
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void SavePerson_WhenPersonNull_ThrowsArgumentNullException()
        {
            Person person = null;

            _simplePersonManager.SavePerson(person);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void SavePerson_WhenPersonNameEmpty_ThrowsArgumentException()
        {
            var person = new Person();
            person.Name = "";

            _simplePersonManager.SavePerson(person);
        }

        [TestMethod]
        [ExpectedException(typeof(DuplicatePersonException))]
        public void SavePerson_WhenSavingDuplicatePerson_ThrowsDuplicatePersonException()
        {
            var person = new Person();
            person.Name = "person name";

            _mockRepository.Setup(r => r.RetrievePerson(person.Name)).Returns(new Person());

            _simplePersonManager.SavePerson(person);
        }
    }
}
